package pl.edu.mimuw.irs.core.model.analysis.subnet;

import java.util.LinkedHashMap;
import java.util.Map;

import pl.edu.mimuw.irs.core.model.analysis.RequirementPlace;
import pl.edu.mimuw.irs.core.model.analysis.ResourcePlace;
import pl.edu.mimuw.irs.core.model.design.IRSActivity;
import pl.edu.mimuw.irs.core.model.design.IRSRequirement;
import pl.edu.mimuw.irs.core.model.design.processing.Requirement;
import pl.edu.mimuw.irs.core.model.design.processing.Resource;
import pl.edu.mimuw.irs.core.model.petrinet.Arc;
import pl.edu.mimuw.irs.core.model.petrinet.Net;
import pl.edu.mimuw.irs.core.model.petrinet.Place;
import pl.edu.mimuw.irs.core.model.petrinet.Transition;

@Deprecated
public class HiringSubnet extends Net {

	private static final long serialVersionUID = -4915361340043678064L;

	// *** Attributes
	
	private Requirement firstRequirement;
	private Requirement lastRequirement;
	private Map<Requirement, Place> requirements;
	private Map<Resource, Place> resources;
	private Map<Requirement, Map<Resource, Transition>> hireTransitions;
	private Map<Transition, Map<Resource, Arc>> allowanceArcs;
	public Requirement getFirstRequirement() {
		return firstRequirement;
	}
	public void setFirstRequirement(Requirement firstRequirement) {
		this.firstRequirement = firstRequirement;
	}
	public Requirement getLastRequirement() {
		return lastRequirement;
	}
	public void setLastRequirement(Requirement lastRequirement) {
		this.lastRequirement = lastRequirement;
	}
	public Map<Requirement, Place> getRequirements() {
		if (requirements == null) requirements = new LinkedHashMap<Requirement, Place>();
		return requirements;
	}
	public void setRequirements(Map<Requirement, Place> requirements) {
		this.requirements = requirements;
	}
	public Map<Resource, Place> getResources() {
		if (resources == null) resources = new LinkedHashMap<Resource, Place>();
		return resources;
	}
	public void setResources(Map<Resource, Place> resources) {
		this.resources = resources;
	}
	public Map<Requirement, Map<Resource, Transition>> getHireTransitions() {
		if (hireTransitions == null) hireTransitions = 
			new LinkedHashMap<Requirement, Map<Resource, Transition>>();
		return hireTransitions;
	}
	public void setHireTransitions(
			Map<Requirement, Map<Resource, Transition>> hireTransitions) {
		this.hireTransitions = hireTransitions;
	}
	public Map<Transition, Map<Resource, Arc>> getAllowanceArcs() {
		if (allowanceArcs == null) allowanceArcs = 
			new LinkedHashMap<Transition, Map<Resource, Arc>>();
		return allowanceArcs;
	}
	public void setAllowanceArcs(
			Map<Transition, Map<Resource, Arc>> allowanceArcs) {
		this.allowanceArcs = allowanceArcs;
	}
	public void addResourcePlace(ResourcePlace resource) {
		Place oldPlace = getResources().get(resource.getResource());
		if (oldPlace != null) removeNode(oldPlace);
		getResources().put(resource.getResource(), resource);
		addPlace(resource);
	}
	public void addRequirementPlace(RequirementPlace requirement) {
		Place oldPlace = getRequirements().get(requirement.getRequirement());
		if (oldPlace != null) removeNode(oldPlace);
		// getRequirements().put(requirement.getRequirement(), requirement);
		addPlace(requirement);
	}
	public Transition getHireTransition(Requirement requirement, Resource resource) {
		Map<Resource, Transition> transitionMap = getHireTransitions().get(requirement);
		if (transitionMap == null) {
			return null;
		} else {
			return transitionMap.get(resource);
		}
	}
	public void setHireTransition(Requirement requirement, Resource resource, Transition transition) {
		Map<Resource, Transition> transitionMap = getHireTransitions().get(requirement);
		if (transitionMap == null) {
			transitionMap = new LinkedHashMap<Resource, Transition>();
			getHireTransitions().put(requirement, transitionMap);
		}
		Transition oldTransition = transitionMap.get(resource);
		if (oldTransition != null) removeNode(oldTransition);
		transitionMap.put(resource, transition);
		addTransition(transition);
	}
	public Arc getAllowanceArc(Transition hire, Resource allowedResource) {
		Map<Resource, Arc> arcMap = getAllowanceArcs().get(hire);
		if (arcMap == null) {
			return null;
		} else {
			return arcMap.get(allowedResource);
		}
	}
	public void setAllowanceArc(Transition hire, Resource allowedResource, Arc allowanceArc) {
		Map<Resource, Arc> arcMap = getAllowanceArcs().get(hire);
		if (arcMap == null) {
			arcMap = new LinkedHashMap<Resource, Arc>();
			getAllowanceArcs().put(hire, arcMap);
		}
		Arc oldArc = arcMap.get(allowedResource);
		if (oldArc != null) removeArc(oldArc.getId());
		arcMap.put(allowedResource, allowanceArc);
		addArc(allowanceArc);
	}
	
	// *** Constructors

	public HiringSubnet(IRSActivity activity, IRSRequirement resourceSet) {
		/*
		//List<Requirement> requirements = activity.getRequirements();
		List<Resource> resources = resourceSet.getContainer().getList();
		List<Edge> edges = createEdges(requirements, resources);
		
		MaxMatch maxMatchFinder = new ExponentialMaxMatch(
				requirements, resources, edges);
		
		List<List<Edge>> maxMatches = maxMatchFinder.findAllMaxMatches();
		
		buildHiringPart(activity, resourceSet, maxMatches);
		*/
	}
	/*
	private void buildHiringPart(IRSActivity activity,
			IRSResourceSet resourceSet, List<List<Edge>> maxMatches) {

		List<Requirement> requirements = activity.getRequirements();
		List<Resource> resources = resourceSet.getContainer().getList();
		
		for (Resource resource : resources) {
			ResourcePlace resourcePlace = new ResourcePlace(resource);
			addResourcePlace(resourcePlace);
			resourcePlace.setPosition(
					new Position(110 + 50 * (getResources().size() - 1), 110));
		}
		
		Requirement firstRequirement = null;
		Requirement lastRequirement = null;
		
		for (List<Edge> maxMatch : maxMatches) {
			Edge nextEdge = maxMatch.get(0);
			Requirement nextRequirement = (Requirement)nextEdge.getNode1();
			Resource nextResource = (Resource)nextEdge.getNode2();
			
			Place nextRequirementPlace = getRequirements().get(nextRequirement);
			if (nextRequirementPlace == null) {
				nextRequirementPlace = new RequirementPlace(nextRequirement);
				addRequirementPlace((RequirementPlace)nextRequirementPlace);
				nextRequirementPlace.setPosition(
						new Position(160 + 50 * resources.size(), 
								110 + 50 * (getRequirements().size() - 1)));
			}
			
			Place requirementPlace = null;
			for (int i = 0; i < maxMatch.size(); i++) {
				
				// Setting helpful last and first RequirementPlace
				if (firstRequirement == null) firstRequirement = nextRequirement;
				lastRequirement = nextRequirement;
				
				// Initializing variables for this iteration
				Requirement requirement = nextRequirement;
				Resource resource = nextResource;
				if (i < maxMatch.size() - 1) {
					nextEdge = maxMatch.get(i + 1);
					nextRequirement = (Requirement)nextEdge.getNode1();
					nextResource = (Resource)nextEdge.getNode2();
					requirementPlace = nextRequirementPlace;
					nextRequirementPlace = getRequirements().get(nextRequirement);
					if (nextRequirementPlace == null) {
						nextRequirementPlace = new RequirementPlace(nextRequirement);
						addRequirementPlace((RequirementPlace)nextRequirementPlace);
						nextRequirementPlace.setPosition(
								new Position(160 + 50 * resources.size(), 
										110 + 50 * (getRequirements().size() - 1)));
					}
				} else {
					requirementPlace = nextRequirementPlace;
				}
				
				Place resourcePlace = getResources().get(resource);
				if (resourcePlace == null) {
					resourcePlace = new ResourcePlace(resource);
					addResourcePlace((ResourcePlace)resourcePlace);
				}
				
				Transition hireTransition = getHireTransition(requirement, resource);
				if (hireTransition == null) {
					hireTransition = new HireTransition(resource);
					setHireTransition(requirement, resource, hireTransition);
					addArc(requirementPlace, hireTransition);
					addArc(resourcePlace, hireTransition, i + 1);
					if (i < maxMatch.size() - 1) 
						addArc(hireTransition, nextRequirementPlace);
					hireTransition.setPosition(
							new Position(135 + 50 * resources.indexOf(resource), 
							160 + 50 * requirements.indexOf(requirement)));
				}
				
				for (int j = i + 1; j < maxMatch.size(); j++) {
					Edge allowedEdge = maxMatch.get(j);
					Resource allowedResource = (Resource)allowedEdge.getNode2();
					Arc allowanceArc = getAllowanceArc(hireTransition, allowedResource);
					if (allowanceArc == null) {
						Place allowedResourcePlace = getResources().get(allowedResource);
						allowanceArc = new Arc(hireTransition, allowedResourcePlace);
						setAllowanceArc(hireTransition, allowedResource, allowanceArc);
					}
				}
			}
		}
		
		setFirstRequirement(firstRequirement);
		setLastRequirement(lastRequirement);
	}
	// *** Methods

	private List<Edge> createEdges(List<Requirement> requirements2, List<Resource> resources2) {
		List<Edge> edges = new LinkedList<Edge>();
		for (Requirement requirement : requirements2) {
			for (Resource resource : resources2) {
				if (resource.meets(requirement)) 
					edges.add(new Edge(requirement, resource));
			}
		}
		return edges;
	}*/
}
